home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 52 / Amiga Format AFCD52 (Issue 136, May 2000).iso / -serious- / programming / other / systracker_src / src / st_patches.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-28  |  9.7 KB  |  365 lines

  1. /***************************************************************************/
  2. /* st_patches - Patch control module.                                      */
  3. /*                                                                         */
  4. /* Copyright © 1999-2000 Andrew Bell. All rights reserved.                 */
  5. /***************************************************************************/
  6.  
  7. #include "SysTracker_rev.h"
  8. #include "st_include.h"
  9. #include "st_protos.h"
  10. #include "st_strings.h"
  11.  
  12. /***************************************************************************/
  13. /* Patch variables */
  14. /***************************************************************************/
  15.  
  16. APTR OriginalOpenLibrary = NULL;
  17. APTR OriginalCloseLibrary = NULL;
  18. APTR OriginalOpenDevice = NULL;
  19. APTR OriginalCloseDevice = NULL;
  20. APTR OriginalOpenFont = NULL;
  21. APTR OriginalCloseFont = NULL;
  22. APTR OriginalOpen = NULL;
  23. APTR OriginalClose = NULL;
  24. APTR OriginalLock = NULL;
  25. APTR OriginalUnLock = NULL;
  26. APTR OriginalOpenFromLock = NULL;
  27.  
  28. /* Use the PATCH_AllocVec() routine (in the st_patches module) to safely
  29.    allocate memory on this pool. Use PATCH_FreeVec() to free it. */
  30.  
  31. APTR PatchPool;
  32. struct SignalSemaphore PatchPoolKey;
  33. BOOL PatchesInstalled = FALSE;
  34.  
  35. struct PatchData
  36. {
  37.   struct Library **pd_BasePtr;
  38.   LONG             pd_LVO;
  39.   APTR             pd_PatchCode;
  40.   APTR            *pd_OrigFunc;
  41.   APTR             pd_AlienFunc;
  42.   UBYTE           *pd_LVOName;
  43. };
  44.  
  45. struct PatchData PD[] = 
  46. {
  47.   /************** OpenLibrary()/CloseLibrary() *************************/
  48.  
  49.   { (struct Library **) &SysBase,
  50.     (LONG) &LVOOpenLibrary,
  51.     &PATCH_NewOpenLibrary,
  52.     &OriginalOpenLibrary,
  53.     NULL,
  54.     "exec.library/OpenLibrary()" },
  55.  
  56.   { (struct Library **) &SysBase,
  57.     (LONG) &LVOCloseLibrary,
  58.     &PATCH_NewCloseLibrary,
  59.     &OriginalCloseLibrary,
  60.     NULL,
  61.     "exec.library/CloseLibrary()" },
  62.  
  63.   /************** OpenDevice()/CloseDevice() ***************************/
  64.  
  65.   { (struct Library **) &SysBase,
  66.     (LONG) &LVOOpenDevice,
  67.     &PATCH_NewOpenDevice,
  68.     &OriginalOpenDevice,
  69.     NULL,
  70.     "exec.library/OpenDevice()" },
  71.  
  72.   { (struct Library **) &SysBase,
  73.     (LONG) &LVOCloseDevice,
  74.     &PATCH_NewCloseDevice,
  75.     &OriginalCloseDevice,
  76.     NULL,
  77.     "exec.library/CloseDevice()" },
  78.  
  79.   /************** OpenFont()/CloseFont() *******************************/
  80.  
  81.   { (struct Library **) &GfxBase,
  82.     (LONG) &LVOOpenFont,
  83.     &PATCH_NewOpenFont,
  84.     &OriginalOpenFont,
  85.     NULL,
  86.     "graphics.library/OpenFont()" },
  87.     
  88.   { (struct Library **) &GfxBase,
  89.     (LONG) &LVOCloseFont,
  90.     &PATCH_NewCloseFont,
  91.     &OriginalCloseFont,
  92.     NULL,
  93.     "graphics.library/CloseFont()" },
  94.  
  95.   /************** Open()/Close() ***************************************/
  96.  
  97.   { (struct Library **) &DOSBase,
  98.     (LONG) &LVOOpen,
  99.     &PATCH_NewOpen,
  100.     &OriginalOpen,
  101.     NULL,
  102.     "dos.library/Open()" },
  103.  
  104.   { (struct Library **) &DOSBase,
  105.     (LONG) &LVOClose,
  106.     &PATCH_NewClose,
  107.     &OriginalClose,
  108.     NULL,
  109.     "dos.library/Close()" },
  110.  
  111.   /************** Lock()/UnLock() **************************************/
  112.  
  113.   { (struct Library **) &DOSBase,
  114.     (LONG) &LVOLock,
  115.     &PATCH_NewLock,
  116.     &OriginalLock,
  117.     NULL,
  118.     "dos.library/Lock()" },
  119.  
  120.   { (struct Library **) &DOSBase,
  121.     (LONG) &LVOUnLock,
  122.     &PATCH_NewUnLock,
  123.     &OriginalUnLock,
  124.     NULL,
  125.     "dos.library/UnLock()" },
  126.  
  127.   /************** OpenFromLock() ***************************************/
  128.  
  129.   { (struct Library **) &DOSBase,
  130.     (LONG) &LVOOpenFromLock,
  131.     &PATCH_NewOpenFromLock,
  132.     &OriginalOpenFromLock,
  133.     NULL,
  134.     "dos.library/OpenFromLock()" },
  135.  
  136.   /*********************************************************************/
  137.  
  138.   { NULL,
  139.     0,
  140.     NULL,
  141.     NULL,
  142.     NULL,
  143.     "" }
  144. };
  145.  
  146. /***************************************************************************/
  147. /* Note: These PATCH_#? routines are called on the context of the
  148.          ARTL-Handler thread. We need to keep them thread safe incase we
  149.          decide to call any of the code from the main SysTracker thread.
  150.  
  151.    Idea: Look for SegTracker, if it's available use it to determine where
  152.          the alien LVOs are pointing to. */
  153.  
  154. GPROTO BOOL PATCH_Init( void )
  155. {
  156.   /*********************************************************************
  157.    *
  158.    * PATCH_Init()
  159.    *
  160.    * Install the patches onto the system and allocate any related
  161.    * resources such as the PatchPool. The semaphore for this pool is
  162.    * also initialized.
  163.    *
  164.    *********************************************************************
  165.    *
  166.    */
  167.  
  168.   register struct PatchData *PDPtr = PD;
  169.  
  170.   PatchesInstalled = FALSE;
  171.   
  172.   /* Setup a semaphore protected multiple task memory pool. This pool
  173.      is used by the installed patches for PatchMsgs, etc. */
  174.   
  175.   memset(&PatchPoolKey, 0, sizeof(struct SignalSemaphore));
  176.   InitSemaphore((struct SignalSemaphore *) &PatchPoolKey);
  177.  
  178.   PatchPool = (APTR) CreatePool(MEMF_CLEAR | MEMF_PUBLIC,
  179.                                   POOL_PUDDLESIZE, POOL_THRESHSIZE);
  180.  
  181.   if (!PatchPool) return FALSE;
  182.  
  183.   Forbid();
  184.   while (PDPtr->pd_BasePtr)
  185.   {
  186.     *PDPtr->pd_OrigFunc = SetFunction(*PDPtr->pd_BasePtr,
  187.                                        PDPtr->pd_LVO,
  188.                                        PDPtr->pd_PatchCode);                                       
  189.  
  190.     PDPtr++;
  191.   }
  192.   PatchesInstalled = TRUE;
  193.   Permit();
  194.  
  195.   return TRUE;
  196. }
  197.  
  198. GPROTO BOOL PATCH_Free( void )
  199. {
  200.   /*********************************************************************
  201.    *
  202.    * PATCH_Free()
  203.    *
  204.    * Attempt to remove the resources and patches installed by
  205.    * PATCH_Init(). This routine will return TRUE on success or FALSE on
  206.    * failure. This routine will also free any resources allocated by
  207.    * PATCH_Init().
  208.    *
  209.    *********************************************************************
  210.    *
  211.    */
  212.  
  213.   if (PatchesInstalled)
  214.   {
  215.     register UBYTE *StrVec = NULL;
  216.     Forbid();
  217.     if (PATCH_CheckUnpatch())
  218.     {
  219.       /* All patches can now be removed. */
  220.  
  221.       register struct PatchData *PDPtr = PD;
  222.       while (PDPtr->pd_BasePtr)
  223.       {
  224.         SetFunction(*PDPtr->pd_BasePtr,
  225.                      PDPtr->pd_LVO,
  226.                     *PDPtr->pd_OrigFunc);
  227.         PDPtr++;
  228.       }
  229.       PatchesInstalled = FALSE;
  230.       Permit();
  231.       return TRUE; /* Patches were successfully removed. */
  232.     }
  233.     else
  234.     {
  235.       Permit();
  236.  
  237.       if (StrVec = MEM_AllocVec(1024L))  /* Grab some memory for the string */
  238.       {
  239.         register UBYTE *LVOInfoStr = STR_Get(SID_LVO_POINTS_TO);
  240.         UBYTE LVOInfoBuf[64];
  241.         register struct PatchData *PDPtr = PD;
  242.  
  243.         /* Construct the failure string. */
  244.  
  245.         strcpy(StrVec, STR_Get(SID_CANT_REMOVE_PATCHES));
  246.         while (PDPtr->pd_BasePtr)
  247.         {
  248.           strcat(StrVec, PDPtr->pd_LVOName);
  249.           strcat(StrVec, " ");
  250.  
  251.           if (PDPtr->pd_AlienFunc == NULL)
  252.           {
  253.             strcat(StrVec, STR_Get(SID_LVO_OK));
  254.           }
  255.           else
  256.           {
  257.             sprintf(LVOInfoBuf, LVOInfoStr,
  258.               PDPtr->pd_AlienFunc, PDPtr->pd_PatchCode);
  259.             strcat(StrVec, LVOInfoBuf);
  260.           }
  261.  
  262.           PDPtr++;
  263.         }
  264.         if (StrVec[strlen(StrVec) - 2] == ',')
  265.           StrVec[strlen(StrVec) - 2] = ' ';
  266.         strcat(StrVec, STR_Get(SID_PLEASE_REMOVE_HACKS));
  267.         GUI_Popup(STR_Get(SID_ERROR_REMOVING_PATCHES),
  268.                   StrVec, NULL, STR_Get(SID_OK_I_WILL));
  269.  
  270.         MEM_FreeVec(StrVec);  
  271.       }
  272.       return FALSE; /* One or more of the LVOs have changed since
  273.                        PATCH_Init() was called. */
  274.     }
  275.   }
  276.  
  277.   if (PatchPool)
  278.   {
  279.     DeletePool(PatchPool); PatchPool = NULL;
  280.   }
  281.   return TRUE; /* Routine was successful. */
  282. }
  283.  
  284. GPROTO BOOL PATCH_CheckUnpatch( void )
  285. {
  286.   /*********************************************************************
  287.    *
  288.    * PATCH_CheckUnpatch()
  289.    *
  290.    * Determine if it's OK to remove our patches, if not, identify those
  291.    * LVOs that have since been patched after PATCH_Init() was called.
  292.    *
  293.    * This routine will return FALSE if SysTracker's patches cannot be
  294.    * removed. This code should really be called under a Forbid().
  295.    *
  296.    *********************************************************************
  297.    *
  298.    */
  299.  
  300.   register BOOL Success = TRUE;
  301.   register struct PatchData *PDPtr = PD;
  302.  
  303.   Forbid();
  304.   while (PDPtr->pd_BasePtr)
  305.   {
  306.     PDPtr->pd_AlienFunc = PATCH_CheckLVO(*PDPtr->pd_BasePtr,
  307.                                           PDPtr->pd_LVO,
  308.                                           PDPtr->pd_OrigFunc,
  309.                                           PDPtr->pd_PatchCode);
  310.     if (PDPtr->pd_AlienFunc != NULL)
  311.       Success = FALSE;
  312.  
  313.     PDPtr++;
  314.   }
  315.   Permit();
  316.   return Success;
  317. }
  318.  
  319. LPROTO APTR PATCH_CheckLVO( struct Library *LibBase, LONG LVO,
  320.   APTR OrigFunc, APTR ShouldBeFunc )
  321. {
  322.   /*********************************************************************
  323.    *
  324.    * PATCH_CheckLVO()
  325.    *
  326.    * Check an individual LVO to see if it points to the provided
  327.    * function pointer. This routine will return NULL if the patch is
  328.    * OK, else a pointer to the alien function.
  329.    *
  330.    * Parameters
  331.    * ----------
  332.    *
  333.    * LibBase      - LibBase of the library that the LVO belongs to.
  334.    * LVO          - LVO in question.
  335.    * OrigFunc     - The function that you replaced. i.e. the pointer
  336.    *                returned by SetFunction() when you first installed
  337.    *                your patch.
  338.    * ShouldBeFunc - What the LVO should point to. i.e. the function
  339.    *                pointer you passed to SetFunction()'s newFunction
  340.    *                paramter, when you first installed your patch.
  341.    *
  342.    *********************************************************************
  343.    *
  344.    */
  345.  
  346.   register APTR AlienFunc = NULL;
  347.   register APTR CurrentFunc = NULL;
  348.  
  349.   Forbid();
  350.   CurrentFunc = SetFunction(LibBase, LVO, OrigFunc);
  351.   if (CurrentFunc != ShouldBeFunc)
  352.   {
  353.     AlienFunc = CurrentFunc;
  354.   }
  355.   SetFunction(LibBase, LVO, CurrentFunc);
  356.   Permit();
  357.   return AlienFunc;
  358. }
  359.  
  360.  
  361.  
  362.  
  363.  
  364.  
  365.